#pragma once
#include "thread.hpp"
#include <queue>
#include <vector>

#define thread_num 3
using namespace MYthread;
template <class T>
class Threadpool
{
public:
    Threadpool():thread_num_(thread_num)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&cond_, nullptr);
        tid_.resize(thread_num_);
    }

    void push(T task)
    {
        taskqueue_.push(task);
        pthread_cond_signal(&cond_);
    }

    void run()
    {
        for (int i = 0; i < thread_num_; i++)
        {
            Thread t;
            t.thread_start(thread_task, (void*)this);
        }
    }

    ~Threadpool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
        
    }
private:
    static void* thread_task(void* arg)
    {
        Threadpool<T>* tp = static_cast<Threadpool<T>*>(arg);
        while(true)
        {
            tp->thread_lock();
            while(tp->queue_size() == 0)
            {
                tp->cond_wait();
            }
            T t = tp->queue_back();
            tp->queue_pop();
            tp->thread_unlock();
            t();
        }
        
        
        return nullptr;
    }
    void thread_lock(void){pthread_mutex_lock(&mutex_);}
    void thread_unlock(void){pthread_mutex_unlock(&mutex_);}
    void cond_wait(void){pthread_cond_wait(&cond_, &mutex_);}
    int queue_size(void){return taskqueue_.size();}
    T queue_back(){return taskqueue_.back();}
    void queue_pop(){taskqueue_.pop();}
private:
    int thread_num_;
    std::vector<int> tid_;
    pthread_mutex_t mutex_;
    pthread_cond_t cond_;

    std::queue<T> taskqueue_;
};